package com.springboot.test.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.springboot.test.common.exception.BizException;
import com.springboot.test.common.enums.ErrorCode;
import com.springboot.test.common.enums.StaticKey;
import com.springboot.test.common.utils.ConvertUtils;
import com.springboot.test.entity.UserEntity;
import com.springboot.test.entity.mapper.UserMapper;
import com.springboot.test.service.param.*;
import com.springboot.test.service.result.UserDetailResult;
import com.springboot.test.service.result.UserInfoResult;
import com.springboot.test.service.result.UserResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class UserService extends ServiceImpl<UserMapper, UserEntity> {

    @Resource
    private RedisService redisService;

    @Resource
    private UserMapper userMapper;

    /**
     * 插入用户
     *
     * @param addUserParam
     * @return
     */
    public Void insert(AddUserParam addUserParam) {
        UserEntity userEntity = queryOneByIdOrPhone(addUserParam.getUserId(), addUserParam.getPhone());
        if (userEntity != null) {
            throw new BizException(ErrorCode.USER_ID_PHONE_EXIST);
        }
        userEntity.setUserId(addUserParam.getUserId());
        userEntity.setEmail(addUserParam.getEmail());
        userEntity.setPhone(addUserParam.getPhone());
        userEntity.setUserName(addUserParam.getUserName());
        userEntity.setNickName(addUserParam.getNickName());
        userEntity.setAvatar("https://nbut-business.oss-cn-hangzhou.aliyuncs.com/12c954518bb74edf841ca50a3e55d349013394d9e91a0f27d7c2090df4cf437c.jpeg");
        String password = DigestUtils.md5DigestAsHex(addUserParam.getPassword().getBytes(StandardCharsets.UTF_8));
        userEntity.setPassword(password);
        save(userEntity);
        log.info("插入成功");
        return null;
    }

    public List<UserEntity> listByUserCodes(Collection<String> userCodes) {
        return list(new QueryWrapper<UserEntity>().lambda().in(UserEntity::getUserId, userCodes));
    }

    public List<UserEntity> listByUserName(String userName){
        return list(new QueryWrapper<UserEntity>().lambda().like(UserEntity::getNickName,userName));
    }

    /**
     * 用户登录
     *
     * @param param
     * @return
     */
    public String login(LoginParam param) {
        UserEntity userEntity = queryOneByIdOrPhone(param.getUserId(), param.getUserId());
        if (userEntity == null) {
            throw new BizException(ErrorCode.USER_NOT_EXIST);
        }
        if(userEntity.getStatus()==1){
            throw new BizException(ErrorCode.USER_BLOCK);
        }
        String password = DigestUtils.md5DigestAsHex(param.getPassword().getBytes(StandardCharsets.UTF_8));
        if (password.equals(userEntity.getPassword())) {
            String token;
            token = redisService.saveUserInfo(userEntity);
            userEntity.setLastLoginTime(new Date());
            updateById(userEntity);
            log.info("token:" + token);
            return token;
        }
        throw new BizException(ErrorCode.PASSWORD_ERROR);
    }

    /**
     * 分页返回全部用户数据
     *
     * @param param
     * @return
     */
    public Page<UserResult> resultPage(UserPageParam param) {
        Page<UserEntity> page = page(new Page<>(param.getPageNum(), param.getPageSize()), new QueryWrapper<UserEntity>()
                .lambda()
                .like(StringUtils.isNotBlank(param.getUserName()), UserEntity::getUserName, param.getUserName())
                .like(StringUtils.isNotBlank(param.getUserId()), UserEntity::getUserId, param.getUserId())
                .like(StringUtils.isNotBlank(param.getEmail()), UserEntity::getEmail, param.getEmail())
                .like(StringUtils.isNotBlank(param.getNickName()), UserEntity::getNickName, param.getNickName())
                .like(StringUtils.isNotBlank(param.getPhone()), UserEntity::getPhone, param.getPhone())
                .between(StringUtils.isNotBlank(param.getStartLastLoginTime())&&StringUtils.isNotBlank(param.getEndLastLoginTime())
                        ,UserEntity::getLastLoginTime,param.getStartLastLoginTime(),param.getEndLastLoginTime())
                .orderByDesc(UserEntity::getCreateTime)
        );
        List<UserResult> resultList = ConvertUtils.convert(page.getRecords(), UserResult.class);
        Page<UserResult> resultPage = new Page<>();
        resultPage.setRecords(resultList);
        resultPage.setCurrent(page.getCurrent());
        resultPage.setSize(page.getSize());
        resultPage.setTotal(page.getTotal());
        return resultPage;
    }

    public UserInfoResult info(String userCode){
        UserEntity userEntity = queryOneByCode(userCode);
        UserInfoResult userInfoResult = new UserInfoResult();
        if(userEntity != null){
            userInfoResult.setUserId(userEntity.getUserId());
            userInfoResult.setNickName(userEntity.getNickName());
            userInfoResult.setAvatar(userEntity.getAvatar());
        }else {
            userInfoResult.setUserId("");
            userInfoResult.setNickName("不存在的用户");
            userInfoResult.setAvatar("https://nbut-business.oss-cn-hangzhou.aliyuncs.com/12c954518bb74edf841ca50a3e55d349013394d9e91a0f27d7c2090df4cf437c.jpeg");
        }
        return userInfoResult;
    }

    public UserDetailResult detail(String userCode){
        UserEntity userEntity = queryOneByCode(userCode);
        if(userEntity != null){
            return ConvertUtils.convert(userEntity,UserDetailResult.class);
        }
        return new UserDetailResult();
    }

    public Boolean updateDetail(UpdateDetailParam param,String userCode){
        UserEntity userEntity = queryOneByCode(userCode);
        userEntity.setUserName(param.getUserName());
        userEntity.setEmail(param.getEmail());
        userEntity.setNickName(param.getNickName());
        userEntity.setAvatar(param.getAvatar());
        //todo 更新缓存数据
        return updateById(userEntity);
    }

    public Boolean updatePassword(UpdatePasswordParam param,String userCode,String token){
        UserEntity userEntity = queryOneByCode(userCode);
        String password = DigestUtils.md5DigestAsHex(param.getOldPassword().getBytes(StandardCharsets.UTF_8));
        if(!userEntity.getPassword().equals(password)){
            throw new BizException(ErrorCode.OLD_PASSWORD_ERROR);
        }
        userEntity.setPassword(DigestUtils.md5DigestAsHex(param.getOldPassword().getBytes(StandardCharsets.UTF_8)));
        updateById(userEntity);
        logout(token);
        return Boolean.TRUE;
    }

    public Boolean logout(String token){
        redisService.removeToken(token);
        return true;
    }

    public String test(String userCode) {
        return userCode;
    }

    public UserEntity queryOneByIdOrPhone(String userId, String phone) {
        return getOne(new QueryWrapper<UserEntity>().lambda()
                .eq(UserEntity::getUserId, userId)
                .or()
                .eq(UserEntity::getPhone, phone)
        );
    }

    public UserEntity queryOneByCode(String userCode){
        return getOne(new QueryWrapper<UserEntity>().lambda()
                .eq(UserEntity::getUserId, userCode)
        );
    }

    public Boolean batchBlock(List<String> ids) {
        List<UserEntity> list = list(new QueryWrapper<UserEntity>().lambda().in(UserEntity::getUserId,ids));
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(a->{
                a.setStatus(1);
            });
            updateBatchById(list);
        }
        return Boolean.TRUE;
    }

    public Boolean updateStatus(Integer status, String userId) {
        UserEntity userEntity = getOne(new QueryWrapper<UserEntity>().lambda().eq(UserEntity::getUserId,userId));
        if(userEntity!=null){
            userEntity.setStatus(status);
            updateById(userEntity);
        }
        return Boolean.TRUE;
    }

    public Boolean delete(String userId) {
        UserEntity userEntity = queryOneByCode(userId);
        if(userEntity!=null){
            removeById(userEntity.getId());
        }
        return Boolean.TRUE;
    }

    public String adminLogin(String username, String password) {
        if("admin".equals(username)&&"admin".equals(password)){
            String token = UUID.randomUUID().toString();
            redisService.expireMin(StaticKey.TOKEN_KEY+"admin",token,StaticKey.TOKEN_TIME);
            return token;
        }
        throw new BizException(ErrorCode.PASSWORD_ERROR);
    }

    /**
     * 定时任务示例
     */
//    @Scheduled(cron = "0/30 * * * * ?")
//    public void taskAgainRun() {
//        LambdaQueryWrapper<DelayCompensateTaskEntity> lambda = new QueryWrapper<DelayCompensateTaskEntity>().lambda();
//        lambda.eq(DelayCompensateTaskEntity::getStatus, DelayStatusEnum.WAITE.getCode());
//        lambda.orderByAsc(DelayCompensateTaskEntity::getExecuteTime);
//        List<DelayCompensateTaskEntity> tasks = delayCompensateTaskMapper.selectList(lambda);
//        tasks.forEach(task -> {
//            //如果比预期执行时间晚30s就触发执行
//            if (DateUtil.getCurrentTimeStamp() - task.getExecuteTime() > 30000) {
//                Runnable r = getExecuteTask(task);
//                ThreadExecutorBuilder.build("delay_task", ThreadEnum.MANUAL.getValue()).
//                        submit(r);
//            }
//        });
//    }
}
